import numpy as np
import math
import random
import copy

avg=lambda l:sum(l)/float(len(l))
sgn=lambda x:x/abs(x)

#I cannot explain my code any further than to say that many situations have been considered
#and each analyzed

sal=[] #average
fal=[] #list of food
lisa=[] #list of always hunter
lisb=[] #list of never hunter
lisc=[]
avgfl=[] #filtered average
lisp=[] #problem times
good=[0]
medl=[] #median
prev=[]
t=0 #total choices made
rp=[0] #those who hunted last time
lastr=[0] #prev rep

def conv(x):
    if x:
        return 'h'
    else:
        return 's'
    
def hunt_choices(rd,fd,sr,m,reput):
    repl=copy.deepcopy(reput)
    p=len(repl) #other player
    n=p+1
    fl=[] #filtered list
    la=0 #always hunt
    lb=0 #always slacks
    lc=0 #50%
    lis=sorted(repl)
    alarm=0 #alarm
    
    sa=avg(repl)
    sal.append(sa) #average
    fal.append(fd) #food
    
    for j in repl:
        if abs(j-0.0)<0.05:
            lb+=1
        elif abs(1.0-j)<0.001:
            la+=1
        else:
            fl.append(j)
        if abs(j-0.5)<0.01:
            lc+=1
        
    lisa.append(la)
    lisb.append(lb)
    lisc.append(lc)
    if len(fl)>0:
        avgfl.append(avg(fl))
    else:
        avgfl.append(0.5)
    if rd == 1:
        good.append(1) #start good
        if n>2:
            lastr[0]=repl[:]
            return ['h' for _ in repl] #hunt for first turn
    elif rd<100 and fd/float(fal[0])<0.6:
        good.append(-1) #bad outcome
        alarm=1 #raise alarm
    elif rd == 100:
        if fd/float(fal[0])>0.85:
            good.append(1) #still good
        else:
            good.append(0) #stop good
    elif fd/float(fal[0])<0.5 and good[-1] == 1:
        good.append(0) #stop good

    if rd>50:
        l1=[sal[-i]-sal[-i-1] for i in range(11)[1:]]
        l2=[sal[-i-10]-sal[-i-11] for i in range(11)[1:]]
        sa1=sum(l1)
        sa2=sum(l2)
        if sa2-sa1>0.5:
            #large reputation change
            if lisp:
                if lisp[-1]!=rd-1:
                    lisp.append(rd)
            else:
                lisp.append(rd)
        l1=[fal[-i]-fal[-i-1] for i in range(11)[1:]]
        l2=[fal[-i-10]-fal[-i-11] for i in range(11)[1:]]
        fa1=sum(l1)
        fa2=sum(l2)
        if fa2-fa1>15 and fal[-1]<fal[-2]:
            #large food drop
            if lisp:
                if lisp[-1]!=rd-1:
                    lisp.append(rd)
            else:
                lisp.append(rd)

    if lb>0.3*n or (la+lc)>0.3*n:
        good[-1]=0
    pq=n-la-lb-1 #middle opponents
    if lisp:
        if rd-lisp[-1]<20 and rd>100 and n<10:
            alarm=1 #bad
            god[-1]=-1
        elif fd<min(100,(300+rd*(2*sr-2)/float(n))):
            alarm=1
            good[-1]=-1
    
    if n!=lb:
        med=lis[max(int(n/2),lb)] #median
        low=lis[max(int(n/5),lb)] #low side
    else:
        med=lis[-1]
        low=lis[-1]
    if good[-1] == -1:
        low=min(sr,low-0.1)
    medl.append(med)
    me=1
    co=0
    c=0
    for i in repl:
        if abs(i-av)<0.05:
            co+=1 #people very close to average
    if co/float(n)>0.3 or la>0.3*n:
        c=1
        
    lisq=[]
    for i in repl:
        if abs(i-sr)<0.01:
            #very close to my reputation
            ret.append(1)
            me+=1
            lisq.append(0)
        elif i<0.1:
            #very slackerish
            ret.append(0)
            lisq.append(1)
        elif good[-1] == 1:
            #good--be nice
            prev.append(rd)
            ret.append(1)
            lisq.append(2)
        elif savg<0.8 and i<=low:
            #low end
            ret.append(0)
            lisq.append(3)
        elif n<=3:
            dif=100
            for j in lastr[0]:
                ls=[]
                if abs(i-j)<=2/float(t)+10**(-5):
                    ls.append(i*t-j*(t-2))
            if len(ls) == 1:
                dif=ls[0]%3
            if abs(dif-2)<0.5:
                ret.append(0)
            elif fd>30 and fd>=fal[-3]:
                if abs(dif-0)<0.5:
                    ret.append(1) #no food loss
                else:
                    ret.append(random.randrange(2))
            elif fd>10:
                if fal[-2]-fd>=4:
                    ret.append(0) #too much food loss
                else:
                    k=0
                    for j in rp[0]:
                        if abs(i-j)<0.05:
                            k=0.5 #hunted w/ me b/f
                            break
                    if i<sr:
                        #less rep than me
                        ret.append(random.random()<k)
                    else:
                        #more rep
                        ret.append(random.random()<(k+0.5))
            else:
                ret.append(0) #low food
            lisq.append(5)
        elif n<=5:
            if fd<30:
                ret.append(0)
            elif i <=min(repl) and fal[-2]-fd<=4:
                ret.append(1)
            else:
                if fd-fal[-2]>=2*(n-2):
                    ret.append(0)
                elif i>0.999:
                    ret.append(0) #i'm so sorry
                else:
                    for j in rp[0]:
                        if abs(i-j)<0.05:
                            ret.append(1)
                            break
                    else:
                        ret.append(0)
            lisq.append(6)
        elif alarm:
            #alarming
            ret.append(random.random()<0.1)
            lisq.append(4)
        elif lb>0.3*n:
            if abs(i-med)>0.2:
                ret.append(sgn(i-med))
            else:
                ret.append(random.randrange(2))
            lisq.append(7)
        elif (la+lc)>=0.3*n and lb>=0.3*n:
            ret.append(0)
            lisq.append(8)
        elif (la+lc)>=0.6*n:
            #special
            ret.append(random.random()<0.3)
            lisq.append(9)
        elif (la+lc)>=0.5*n:
            if i>0.9 and lb>0:
                ret.append(0)
            else:
                ret.append(random.random()<i)
            lisq.append(10)
        elif la>0.3*n:
            #alot of hunters
            ret.append(random.random()<i)
            lisq.append(11)
        elif lc>0.3*n:
            #alot of 50%s
            ret.append(random.random()<i*1.1)
            lisq.append(12)
        elif i>0.9 and lb>=1:
            #hunter
            if la+2>=2*(pq*savg) or la>0.3*n:
                ret.append(random.random()<0.125+av)
            else:
                ret.append(1)
            lisq.append(12.5)
        elif rd<150 and len(repl)>5:
            #early
            if i>=low:
                ret.append(1)
            else:
                ret.append(0)
            lisq.append(13)
        elif rd<200:
            #early2
            ret.append(random.random()<i)
            lisq.append(0)
        elif i<sr or i*n/pq<0.5:
            ret.append((i+0.5*c)>=random.random())
            lisq.append(14)
        else:
            ret.append(1)
            lisq.append(15)
    
    if pq <=1 and me!=n:
        if good[-1] == 0 and rd>110:
            lastr[0]=repl[:]
            return ['s' for i in repl]
    if n-me == 1:
        for i,j in enumerate(repl):
            if abs(j-sr)<0.03:
                ret[i]=1
            else:
                ret[i]=0
    lastr[0]=repl[:]
    retu=map(conv,ret)
    return retu

def hunt_outcomes(food_earnings):
    rp[0]=[]
    for i,j in enumerate(food_earnings):
        if j>=0:
            rp[0].append(lastr[0][i])
    pass

def round_end(award, m, number_hunters):
    pass # do nothing
